import time
import random
import requests
import cv2
from selenium import webdriver
from selenium.webdriver import ActionChains

# 等待元素加载相关
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By


def _tran_canny(image):
    """消除噪声"""
    image = cv2.GaussianBlur(image, (3, 3), 0)
    return cv2.Canny(image, 50, 150)


def detect_displacement(img_slider_path, image_background_path):
    """匹配获取两张图片，找出距离"""
    # # 参数0是灰度模式
    image = cv2.imread(img_slider_path, 0)
    template = cv2.imread(image_background_path, 0)

    # 寻找相同高度(height)匹配的图形
    res = cv2.matchTemplate(_tran_canny(image), _tran_canny(template), cv2.TM_CCOEFF_NORMED)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

    top_left = max_loc[0]  # 横坐标
    # 展示圈出来的区域
    x, y = max_loc  # 获取x,y位置坐标

    w, h = image.shape[::-1]  # 宽高
    cv2.rectangle(template, (x, y), (x + w, y + h), (7, 249, 151), 2)
    # show(template)
    return top_left + 10


class SliderSpider:
    """多缺口滑块爬虫"""
    # 网站登陆页面
    url = 'https://dun.163.com/trial/jigsaw'

    def __init__(self):
        self.browser = None

    def run(self):
        """获取 browser，滑块拼图调用"""
        self.get_browser()
        while True:
            res = self.do_slider()
            if res in ['验证成功', '']:
                print('滑块验证成功！')
                break
            print('正在重试..')

    def get_browser(self):
        """初始化selenium"""
        self.browser = webdriver.Chrome()
        self.browser.maximize_window()
        self.browser.get(self.url)
        # 等待3s用于加载脚本文件
        self.browser.implicitly_wait(2)
        self.browser.execute_script('window.scrollBy(0,250)')
        # 点击弹出式
        self.browser.find_element_by_xpath('//li[@captcha-mode="popup"]').click()
        time.sleep(1)
        # 点击登录
        self.browser.find_element_by_xpath('//button[text()="登录"]').click()

    def do_slider(self):
        """1获取图片 2拖动滑块"""
        time.sleep(1)
        # 等待背景图片出现
        WebDriverWait(self.browser, 10).until(
            EC.presence_of_element_located((By.XPATH, '//img[@class="yidun_bg-img"]')))
        # 获取背景图src
        target_url = self.browser.find_element_by_class_name('yidun_bg-img').get_attribute('src')
        # 获取拼图src
        temp_url = self.browser.find_element_by_class_name('yidun_jigsaw').get_attribute('src')
        with open('temp_target_crop.png', 'wb') as f1:
            response = requests.get(target_url)
            f1.write(response.content)
        with open('temp_temp_crop.png', 'wb') as f2:
            response = requests.get(temp_url)
            f2.write(response.content)

        # 获取缺口距离
        num = detect_displacement('temp_target_crop.png', 'temp_temp_crop.png')
        print('滑块应该移动距离:', num)
        print('开始拖动===')

        # 找到小滑块
        button = self.browser.find_element_by_class_name('yidun_slider')
        # 模拟抛物线
        first_distance = num / 4 * 3
        second_distance = num - first_distance - 3
        third_distance = num - second_distance - first_distance
        print('distances:', first_distance, second_distance, third_distance)

        # 模拟人滑动行为
        ActionChains(self.browser).click_and_hold(button).move_by_offset(first_distance, random.random()).perform()
        time.sleep(0.15)
        ActionChains(self.browser).click_and_hold(button).move_by_offset(second_distance, random.random()).perform()
        time.sleep(0.26)
        ActionChains(self.browser).click_and_hold(button).move_by_offset(third_distance, random.random()).release().perform()
        print('拖动完成===')

        time.sleep(1.5)
        tips = self.browser.find_element_by_xpath('//span[@class="yidun_tips__text yidun-fallback__tip"]').text
        print('验证结果:', tips)
        return tips

    def close(self):
        self.browser.quit()


if __name__ == '__main__':
    spider = SliderSpider()
    spider.run()
    spider.close()
